import { EventEmitter } from 'events';
import { Logger } from '@/types';
import { ConnectionPool, ExtendedConnectionPoolStats } from '../core/connection-pool';
import { createLogger } from '@/patterns';

export interface PoolHealthStatus {
  status: 'healthy' | 'warning' | 'critical';
  score: number; // 0-100
  issues: string[];
  recommendations: string[];
  timestamp: number;
}

export interface PoolAlert {
  level: 'info' | 'warning' | 'error' | 'critical';
  message: string;
  metric: string;
  value: number;
  threshold: number;
  timestamp: number;
}

export interface MonitoringConfig {
  enabled: boolean;
  checkInterval: number;
  alertThresholds: {
    highUtilization: number;      // 连接利用率警告阈值
    criticalUtilization: number;  // 连接利用率严重阈值
    longWaitTime: number;         // 等待时间警告阈值 (ms)
    highFailureRate: number;      // 连接失败率警告阈值 (per minute)
    lowAvailability: number;      // 可用连接数警告阈值
    pendingRequestsThreshold: number; // 等待请求数警告阈值
  };
  retentionPeriod: number; // 历史数据保留时间 (ms)
}

export class ConnectionPoolMonitor extends EventEmitter {
  private readonly pool: ConnectionPool;
  private readonly logger: Logger;
  private readonly config: MonitoringConfig;
  private monitorTimer?: NodeJS.Timeout;
  private statsHistory: Array<ExtendedConnectionPoolStats & { timestamp: number }> = [];
  private alertHistory: PoolAlert[] = [];

  constructor(
    pool: ConnectionPool,
    config: Partial<MonitoringConfig> = {},
    logger?: Logger
  ) {
    super();
    this.pool = pool;
    this.logger = logger ?? createLogger('PoolMonitor');
    this.config = {
      enabled: true,
      checkInterval: 30000, // 30秒检查一次
      alertThresholds: {
        highUtilization: 0.8,      // 80%
        criticalUtilization: 0.95, // 95%
        longWaitTime: 5000,        // 5秒
        highFailureRate: 5,        // 每分钟5次失败
        lowAvailability: 2,        // 少于2个可用连接
        pendingRequestsThreshold: 10, // 超过10个等待请求
      },
      retentionPeriod: 3600000, // 1小时
      ...config,
    };

    if (this.config.enabled) {
      this.startMonitoring();
    }
  }

  public startMonitoring(): void {
    if (this.monitorTimer) {
      return;
    }

    this.logger.info('Starting connection pool monitoring');
    this.monitorTimer = setInterval(() => {
      this.performHealthCheck();
    }, this.config.checkInterval);

    // 立即执行一次检查
    this.performHealthCheck();
  }

  public stopMonitoring(): void {
    if (this.monitorTimer) {
      clearInterval(this.monitorTimer);
      this.monitorTimer = undefined;
      this.logger.info('Stopped connection pool monitoring');
    }
  }

  public getHealthStatus(): PoolHealthStatus {
    const stats = this.pool.getExtendedStats();
    const issues: string[] = [];
    const recommendations: string[] = [];
    let score = 100;

    // 检查连接利用率
    if (stats.connectionUtilization > this.config.alertThresholds.criticalUtilization) {
      issues.push(`Critical connection utilization: ${(stats.connectionUtilization * 100).toFixed(1)}%`);
      recommendations.push('Consider increasing max pool size or optimizing connection usage');
      score -= 30;
    } else if (stats.connectionUtilization > this.config.alertThresholds.highUtilization) {
      issues.push(`High connection utilization: ${(stats.connectionUtilization * 100).toFixed(1)}%`);
      recommendations.push('Monitor connection usage patterns');
      score -= 15;
    }

    // 检查等待时间
    if (stats.averageWaitTime > this.config.alertThresholds.longWaitTime) {
      issues.push(`Long average wait time: ${stats.averageWaitTime.toFixed(0)}ms`);
      recommendations.push('Consider increasing pool size or optimizing connection release');
      score -= 20;
    }

    // 检查失败率
    if (stats.connectionFailureRate > this.config.alertThresholds.highFailureRate) {
      issues.push(`High connection failure rate: ${stats.connectionFailureRate.toFixed(1)}/min`);
      recommendations.push('Check RabbitMQ server health and network connectivity');
      score -= 25;
    }

    // 检查可用连接数
    if (stats.availableConnections < this.config.alertThresholds.lowAvailability) {
      issues.push(`Low available connections: ${stats.availableConnections}`);
      recommendations.push('Monitor connection pool scaling or increase min pool size');
      score -= 15;
    }

    // 检查等待请求数
    if (stats.pendingRequests > this.config.alertThresholds.pendingRequestsThreshold) {
      issues.push(`High pending requests: ${stats.pendingRequests}`);
      recommendations.push('Pool may be undersized for current load');
      score -= 20;
    }

    // 确定健康状态
    let status: PoolHealthStatus['status'];
    if (score >= 80) {
      status = 'healthy';
    } else if (score >= 60) {
      status = 'warning';
    } else {
      status = 'critical';
    }

    return {
      status,
      score: Math.max(0, score),
      issues,
      recommendations,
      timestamp: Date.now(),
    };
  }

  public getStatsHistory(duration: number = 3600000): Array<ExtendedConnectionPoolStats & { timestamp: number }> {
    const cutoff = Date.now() - duration;
    return this.statsHistory.filter(stat => stat.timestamp >= cutoff);
  }

  public getAlertHistory(duration: number = 3600000): PoolAlert[] {
    const cutoff = Date.now() - duration;
    return this.alertHistory.filter(alert => alert.timestamp >= cutoff);
  }

  public getMetricsSummary(duration: number = 3600000): {
    avgUtilization: number;
    avgWaitTime: number;
    totalFailures: number;
    peakConnections: number;
    alertCount: number;
  } {
    const history = this.getStatsHistory(duration);
    const alerts = this.getAlertHistory(duration);

    if (history.length === 0) {
      return {
        avgUtilization: 0,
        avgWaitTime: 0,
        totalFailures: 0,
        peakConnections: 0,
        alertCount: alerts.length,
      };
    }

    const avgUtilization = history.reduce((sum, stat) => sum + stat.connectionUtilization, 0) / history.length;
    const avgWaitTime = history.reduce((sum, stat) => sum + stat.averageWaitTime, 0) / history.length;
    const totalFailures = history.reduce((sum, stat) => sum + stat.connectionFailureRate, 0);
    const peakConnections = Math.max(...history.map(stat => stat.peakConnections));

    return {
      avgUtilization,
      avgWaitTime,
      totalFailures,
      peakConnections,
      alertCount: alerts.length,
    };
  }

  private performHealthCheck(): void {
    try {
      const stats = this.pool.getExtendedStats();
      const timestamp = Date.now();
      
      // 记录统计信息
      this.statsHistory.push({ ...stats, timestamp });
      
      // 清理过期数据
      this.cleanupHistory();
      
      // 检查警告条件
      this.checkAlerts(stats, timestamp);
      
      // 发出监控事件
      this.emit('healthCheck', { stats, timestamp });
      
    } catch (error) {
      this.logger.error('Error during health check:', error as Error);
      this.emit('monitoringError', error);
    }
  }

  private checkAlerts(stats: ExtendedConnectionPoolStats, timestamp: number): void {
    const alerts: PoolAlert[] = [];

    // 检查各种警告条件
    if (stats.connectionUtilization > this.config.alertThresholds.criticalUtilization) {
      alerts.push({
        level: 'critical',
        message: `Critical connection utilization: ${(stats.connectionUtilization * 100).toFixed(1)}%`,
        metric: 'connectionUtilization',
        value: stats.connectionUtilization,
        threshold: this.config.alertThresholds.criticalUtilization,
        timestamp,
      });
    } else if (stats.connectionUtilization > this.config.alertThresholds.highUtilization) {
      alerts.push({
        level: 'warning',
        message: `High connection utilization: ${(stats.connectionUtilization * 100).toFixed(1)}%`,
        metric: 'connectionUtilization',
        value: stats.connectionUtilization,
        threshold: this.config.alertThresholds.highUtilization,
        timestamp,
      });
    }

    if (stats.averageWaitTime > this.config.alertThresholds.longWaitTime) {
      alerts.push({
        level: 'warning',
        message: `Long average wait time: ${stats.averageWaitTime.toFixed(0)}ms`,
        metric: 'averageWaitTime',
        value: stats.averageWaitTime,
        threshold: this.config.alertThresholds.longWaitTime,
        timestamp,
      });
    }

    if (stats.connectionFailureRate > this.config.alertThresholds.highFailureRate) {
      alerts.push({
        level: 'error',
        message: `High connection failure rate: ${stats.connectionFailureRate.toFixed(1)}/min`,
        metric: 'connectionFailureRate',
        value: stats.connectionFailureRate,
        threshold: this.config.alertThresholds.highFailureRate,
        timestamp,
      });
    }

    if (stats.pendingRequests > this.config.alertThresholds.pendingRequestsThreshold) {
      alerts.push({
        level: 'warning',
        message: `High pending requests: ${stats.pendingRequests}`,
        metric: 'pendingRequests',
        value: stats.pendingRequests,
        threshold: this.config.alertThresholds.pendingRequestsThreshold,
        timestamp,
      });
    }

    // 记录和发出警告
    for (const alert of alerts) {
      this.alertHistory.push(alert);
      this.emit('alert', alert);
      
      if (alert.level === 'critical' || alert.level === 'error') {
        this.logger.error(`Pool Alert [${alert.level.toUpperCase()}]: ${alert.message}`);
      } else {
        this.logger.warn(`Pool Alert [${alert.level.toUpperCase()}]: ${alert.message}`);
      }
    }
  }

  private cleanupHistory(): void {
    const cutoff = Date.now() - this.config.retentionPeriod;
    
    this.statsHistory = this.statsHistory.filter(stat => stat.timestamp >= cutoff);
    this.alertHistory = this.alertHistory.filter(alert => alert.timestamp >= cutoff);
  }

  public destroy(): void {
    this.stopMonitoring();
    this.removeAllListeners();
    this.statsHistory = [];
    this.alertHistory = [];
  }
}
